﻿using Microsoft.Data.OData;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http.Dispatcher;
using System.Web.Http.OData;
using System.Web.Http.OData.Query;
using System.Web.Http.OData.Query.Validators;
using WooCoo.Tools;

namespace WooCoo.DataPortal.WebHost.ODataServer
{
    [WCODataQueryParameterBindingAttribute]
    public class WCODataQueryOptions : ODataQueryOptions
    {
        //public ODataQueryOptions InnerODataQueryOptions { get; private set; }        
        public WCODataQueryOptions(ODataQueryContext context, HttpRequestMessage request)
            : base(context, request)
        {
            //InnerODataQueryOptions = new ODataQueryOptions(context, request);
        }
    }
    [WCODataQueryParameterBindingAttribute]
    public class WCODataQueryOptions<TEntity> : WCODataQueryOptions
    {
        public WCODataQueryOptions(ODataQueryContext context, HttpRequestMessage request)
            : base(context, request)
        {
            if (base.Context.ElementClrType == null)
            {
                throw Error.Argument(string.Format("ElementClrType为空", typeof(ODataQueryContext).Name), "context");
            }
            if (context.ElementClrType != typeof(TEntity))
            {
                throw Error.Argument(string.Format("EntityTypeMismatch:{0}与{1}", context.ElementClrType.FullName, typeof(TEntity).FullName), "context");
            }
        }

        /// <summary>Apply the individual query to the given IQueryable in the right order.</summary>
        /// <returns>The query that the query has been applied to.</returns>
        /// <param name="query">The IQueryable that we are applying query against.</param>
        public override IQueryable ApplyTo(IQueryable query)
        {
            WCODataQueryOptions<TEntity>.ValidateQuery(query);
            return base.ApplyTo(query);
        }
        /// <summary>Apply the individual query to the given IQueryable in the right order.</summary>
        /// <returns>The query that the query has been applied to.</returns>
        /// <param name="query">The IQueryable that we are applying query against.</param>
        /// <param name="querySettings">The settings to use in query composition.</param>
        public override IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings)
        {
            WCODataQueryOptions<TEntity>.ValidateQuery(query);
            return base.ApplyTo(query, querySettings);
        }
        private static void ValidateQuery(IQueryable query)
        {
            if (query == null)
            {
                throw Error.ArgumentNull("query");
            }
            if (!typeof(TEntity).IsAssignableFrom(query.ElementType))
            {
                throw Error.Argument(string.Format("CannotApplyODataQueryOptionsOfT",
                    typeof(ODataQueryOptions).Name,
                    typeof(TEntity).FullName,
                    typeof(IQueryable).Name,
                    query.ElementType.FullName), "query");
            }
        }
    }

}
